package device;

import interfaces.IRemoteNode;
import java.net.*;
import java.io.*;

/**
 * @author Stefano&Davide
 * @version 1.0
 */

public class OdometerThreadServerRegistry extends Thread{

	OdometerNoDisplay odometer = null;
	private int port;

	public OdometerThreadServerRegistry(OdometerNoDisplay odometer,int port) {
		this.odometer = odometer;
		this.port=port;
	}

	@Override
	public void run() {
		DatagramSocket socket = null;
		DatagramPacket packet = null;
		byte[] buf = new byte[256];

		try {
			// controllo che la porta sia nel range consentito 1024-65535
			if (port < 1024 || port > 65535) {
				System.out.println("Usage: java UDP_Unicast_Server [serverPort>1024]");
				System.exit(1);
			}
		} catch (NumberFormatException e) {
			System.out.println("Usage: java UDP_Unicast_Server [serverPort>1024]");
			System.exit(1);
		}

		// inizializzazione socket e strutture dati di supporto
		try {
			socket = new DatagramSocket(port);
			packet = new DatagramPacket(buf, buf.length);
			System.out.println("Creata la socket: " + socket);
		} catch (SocketException e) {
			System.out.println("Problemi nella creazione della socket: ");
			e.printStackTrace();
			System.exit(1);
		}

		// relizzazione logica di servizio
		try {
			// dichiarazione oggetti per la lettura/scrittura dei dati come stream di
			// byte nel pacchetto UDP
			ByteArrayInputStream biStream = null;
			DataInputStream diStream = null;
			ByteArrayOutputStream boStream = null;
			DataOutputStream doStream = null;
			byte[] data = null;

			// QUI DICHIARAZIONE DI VARIABILI NECESSARIE PER LA REALIZZAZIONE
			// DELLA LOGICA DEL PROGRAMMA
			String remoteIp=null;
			int remotePort=-1;
			int protocolType=-1;
			while (true) {
				System.out.println("\nIn attesa di richieste...");

				// ricezione del datagramma
				try {
					packet.setData(buf);
					socket.receive(packet);
				} catch (IOException e) {
					System.err.println("Problemi nella ricezione del datagramma: "
							+ e.getMessage());
					e.printStackTrace();
					continue;
					// il server continua a fornire il servizio ricominciando dall'inizio
					// del ciclo
				}

				try {
					biStream = new ByteArrayInputStream(packet.getData(), 0, packet
							.getLength());
					diStream = new DataInputStream(biStream);
					// QUI ESTRAZIONE RICHIESTA DALLO STREAM DI INPUT
					// ad esempio, per la lettura della stringa 


					remoteIp = diStream.readUTF();
					remotePort=diStream.readInt();
					protocolType=diStream.readInt();
				} catch (Exception e) {
					System.err.println("Problemi nella lettura della richiesta: ");
					e.printStackTrace();
					continue;
					// il server continua a fornire il servizio ricominciando dall'inizio
					// del ciclo
				}

				// Realizzazione logica di programma e invio della risposta
				try {
					// QUI LOGICA PER LA REALIZZAZIONE DELLE FUNZIONALITA' RICHIESTE

					boStream = new ByteArrayOutputStream();
					doStream = new DataOutputStream(boStream);

					// QUI INSERIMENTO DATI DI INPUT NELLO STREAM DI OUTPUT
					doStream.writeUTF("Ok");

					// inserimento dati nel pacchetto UDP
					data = boStream.toByteArray();
					packet.setData(data, 0, data.length);

					// invio pacchetto UDP al pari
					socket.send(packet);
				} catch (IOException e) {
					System.err.println("Problemi nell'invio della risposta: "
							+ e.getMessage());
					e.printStackTrace();
					continue;
					// il server continua a fornire il servizio ricominciando dall'inizio
					// del ciclo
				}

				//Creazione oggetto IRemoteNode e registrazione presso Observable
				System.out.println("Registrato oggetto remoto alla porta"+remotePort);
				IRemoteNode remoteNode=new RemoteNode(remoteIp,remotePort,protocolType);
				odometer.addObserver(remoteNode);

			} // while

		}
		// qui catturo le eccezioni non catturate all'interno del while
		// in seguito alle quali il server termina l'esecuzione
		catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("UDP_Unicast_Server: termino...");
		socket.close();
	}

}
